package com.egdigital.allzic.utils;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.provider.Settings;
import android.text.Layout;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.TextView.BufferType;
import android.widget.Toast;

import com.daimajia.androidanimations.library.Techniques;
import com.daimajia.androidanimations.library.YoYo;
import com.egdigital.allzic.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener;

public class Utils {

	private static final String	TAG							= Utils.class.getSimpleName();	// log
	public static final int		ANIMATION_DURATION_FAST		= 200;
	public static final int		ANIMATION_DURATION_MEDIUM	= 500;
	public static final int		ANIMATION_DURATION_SLOW		= 1000;
	public static Toast			CURRENT_TOAST;

	/**
	 * Convert milliseconds time to Timer Format Hours:Minutes:Seconds
	 * 
	 * @param milliseconds
	 *        a time in milliseconds
	 */
	public static String milliSecondsToTimer(long milliseconds) {
		String finalTimerString = "";
		String secondsString = "";
		// Convert total duration into time
		int hours = (int) (milliseconds / (1000 * 60 * 60));
		int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
		int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);
		// Add hours if there
		if (hours > 0) {
			finalTimerString = hours + ":";
		}
		// Prepending 0 to seconds if it is one digit
		if (seconds < 10) {
			secondsString = "0" + seconds;
		} else {
			secondsString = "" + seconds;
		}
		finalTimerString = finalTimerString + minutes + ":" + secondsString;
		// return timer string
		return finalTimerString;
	}

	/**
	 * Function to get Progress percentage
	 * 
	 * @param currentDuration
	 * @param totalDuration
	 */
	public static int getProgressPercentage(long currentDuration, long totalDuration) {
		Double percentage = (double) 0;
		long currentSeconds = (int) (currentDuration / 1000);
		long totalSeconds = (int) (totalDuration / 1000);
		// calculating percentage
		percentage = (((double) currentSeconds) / totalSeconds) * 100;
		// return percentage
		return percentage.intValue();
	}

	/**
	 * Function to change progress to timer
	 * 
	 * @param progress
	 *        -
	 * @param totalDuration
	 *        returns current duration in milliseconds
	 */
	public static int progressToTimer(int progress, int totalDuration) {
		int currentDuration = 0;
		totalDuration = (int) (totalDuration / 1000);
		currentDuration = (int) ((((double) progress) / 100) * totalDuration);
		// return current duration in milliseconds
		return currentDuration * 1000;
	}

	public static String convertMilliToTime(int millis) {
		return String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis), TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), TimeUnit.MILLISECONDS.toSeconds(millis)
				- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
	}

	public static SpannableString constructSpanString(String message, int color) {
		SpannableString spannable = new SpannableString(message);
		spannable.setSpan(new ForegroundColorSpan(color), 0, message.length(), 0);
		return spannable;
	}

	public static void cancelToast() {
		// Avoid creating a queue of toasts
		if (CURRENT_TOAST != null) {
			// Dismiss the current showing Toast
			CURRENT_TOAST.cancel();
		}
	}

	/**
	 * @param message
	 *        a {@link SpannableStringBuilder} that represent the message to display
	 * @param context
	 *        the application context
	 * @param title
	 *        a string for the title
	 * @param istrans
	 *        if you want the toast to be transparent
	 * @param asTitle
	 *        if you want to display the title or not
	 */
	public static void customToast(SpannableStringBuilder message, Context context, boolean istrans) {
		if (CURRENT_TOAST != null) {
			CURRENT_TOAST.cancel(); // Dismiss the current showing Toast
		}
		LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View layout = inflater.inflate(R.layout.view_custom_toast, null);
		CURRENT_TOAST = new Toast(context.getApplicationContext());
		CURRENT_TOAST.setDuration(Toast.LENGTH_LONG);
		CURRENT_TOAST.setView(layout);
		// get
		TextView text = (TextView) layout.findViewById(R.id.text);
		// set
		text.setText(message, BufferType.SPANNABLE);
		text.setTextColor(Color.WHITE);
		if (true) { // TODO: istrans
			layout.setBackgroundColor(context.getResources().getColor(R.color.clr_main_trans));
		}
		CURRENT_TOAST.show();
		if (layout != null) { // Check if the layout is visible - just to be sure
			layout.setOnTouchListener(new OnTouchListener() { // This will listen for any touch event on the screen

				@Override
				public boolean onTouch(View v, MotionEvent event) {
					if (CURRENT_TOAST != null) { // No need to check the event, just dismiss the toast if it is showing
						CURRENT_TOAST.cancel();
						return true; // we return True if the listener has consumed the event
					}
					return false;
				}
			});
		}
	}

	public static synchronized void setImageFromUrl(ImageManager imageManager, String url, ImageView imageView) {
		try {
			imageManager.getmImageLoader().displayImage(url, imageView, imageManager.getmSimpleOptions(), new SimpleImageLoadingListener() {

				@Override
				public void onLoadingStarted(String imageUri, View view) {
					view.setVisibility(View.VISIBLE);
				}

				@Override
				public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
					view.setVisibility(View.VISIBLE);
				}

				@Override
				public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
					YoYo.with(Techniques.FadeIn).duration(500).playOn(view);
				}
			});
		} catch (Exception e) {
		}
	}

	/**
	 * Show a dialog that provide link to the parameter sections of the phone about Wifi and networking
	 * 
	 * @param title
	 * @param msg
	 * @param context
	 *        context of the activity
	 * @param launching
	 *        should the activity finish
	 */
	public static void showNetworkAlert(String title, String msg, final Context context, final boolean launching) {
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
		alertDialog.setTitle(title);
		alertDialog.setOnCancelListener(new OnCancelListener() {

			public void onCancel(DialogInterface dialog) {
			}
		});
		alertDialog.setMessage(msg);
		alertDialog.setNeutralButton("Rˇseau", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
				context.startActivity(intent);
			}
		});
		alertDialog.setPositiveButton("Wifi", new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
				context.startActivity(intent);
			}
		});
		alertDialog.setNegativeButton("Annuler", new DialogInterface.OnClickListener() {

			public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
			}
		});
		alertDialog.show();
	}

	public static boolean isApplicationRunning(ActivityManager activityManager) {
		List<ActivityManager.RunningTaskInfo> alltasks = activityManager.getRunningTasks(1);
		if (alltasks.isEmpty()) {
			return false;
		}
		return true;
	}

	/**
	 * @param activityManager
	 *        an instance of {@link ActivityManager} from the context
	 * @param nomService
	 *        package name of the service
	 * @return <code>true</code> if the service is running, else return <code>false</code>
	 */
	public static boolean isServiceRunning(ActivityManager activityManager, String nomService/* nom de package */) {
		for (RunningServiceInfo service : activityManager.getRunningServices(Integer.MAX_VALUE)) {
			if (service.service.getClassName().contentEquals(nomService)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @param date
	 *        a date as a <code>String</code>
	 * @return the same date with another format
	 */
	public static String formatDate(String date) {
		SimpleDateFormat formatTo = null;
		java.util.Date tmpDate = null;
		String resultDate = "";
		if (date.contains("+")) {
			date = date.substring(0, date.lastIndexOf("+") - 1);
		}
		String[] patterns = {// "EEE, dd MMM yyyy hh:mm:ss UTC",
				"yyyy-MM-dd HH:mm:ss",
				"yyyy.MM.dd G 'at' HH:mm:ss z",
				"EEE, MMM d, ''yy",
				"yyyyy.MMMMM.dd GGG hh:mm aaa",
				"EEE, d MMM yyyy HH:mm:ss Z",
				"yyMMddHHmmssZ",
				"d MMM yyyy HH:mm:ss z",
				"yyyy-MM-dd'T'HH:mm:ss",
				"yyyy-MM-dd'T'HH:mm:ss'Z'",
				"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
				"yyyy-MM-dd'T'HH:mm:ssZ",
				"yyyy-MM-dd'T'HH:mm:ss.SSSZ",
				"yyyy-MM-dd'T'HH:mm:ssz",
				"yyyy-MM-dd'T'HH:mm:ss.SSSz",
				"EEE, d MMM yy HH:mm:ssz",
				"EEE, d MMM yy HH:mm:ss",
				"EEE, d MMM yy HH:mm z",
				"EEE, d MMM yy HH:mm Z",
				"EEE, d MMM yyyy HH:mm:ss z",
				"EEE, d MMM yyyy HH:mm:ss Z",
				"EEE, d MMM yyyy HH:mm:ss ZZZZ",
				"EEE, d MMM yyyy HH:mm z",
				"EEE, d MMM yyyy HH:mm Z",
				"d MMM yy HH:mm z",
				"d MMM yy HH:mm:ss z",
				"d MMM yyyy HH:mm z",
				"d MMM yyyy HH:mm:ss z" };
		for (int i = 0; i < patterns.length; i++) {
			SimpleDateFormat formatFrom = new SimpleDateFormat(patterns[i], Locale.ENGLISH);
			try {
				tmpDate = formatFrom.parse(date);
				break;
			} catch (Exception e) {
			}
		}
		formatTo = new SimpleDateFormat("dd-MM-yyyy HH:mm"); // final date format
		resultDate = formatTo.format(tmpDate);
		return resultDate;
	}

	/**
	 * @return current date in milliseconds
	 */
	public static Long getCurrentDate() {
		// Calendar calendar = Calendar.getInstance(Locale.FRANCE);
		// SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
		// return timeFormat.format(calendar.getTime());
		return System.currentTimeMillis();
	}

	/**
	 * @param position
	 *        position in the list
	 * @param size
	 *        size of the list
	 * @return true if the position is the last, else false
	 */
	public static synchronized boolean isLast(int position, int size) {
		if (position == size - 1) {
			return true;
		}
		return false;
	}

	/**
	 * Check the device to make sure it has the Google Play Services APK. <br>
	 * If it doesn't, display a dialog that allows users to download the APK from the Google Play Store or enable it in the device's system settings.
	 * 
	 * @param context
	 *        application context
	 * @param activity
	 */
	public static boolean checkPlayServices(Context context, Activity activity) {
		final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
		int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
		if (resultCode != ConnectionResult.SUCCESS) {
			if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
				GooglePlayServicesUtil.getErrorDialog(resultCode, activity, PLAY_SERVICES_RESOLUTION_REQUEST).show();
			} else {
				activity.finish();
			}
			return false;
		}
		return true;
	}

	/**
	 * Animation fade out for View
	 */
	public static void fadeOutView(final View img) {
		Animation fadeOut = new AlphaAnimation(1, 0);
		fadeOut.setInterpolator(new AccelerateInterpolator());
		fadeOut.setDuration(500);
		fadeOut.setAnimationListener(new AnimationListener() {

			public void onAnimationEnd(Animation animation) {
				img.setVisibility(View.GONE);
			}

			public void onAnimationRepeat(Animation animation) {
			}

			public void onAnimationStart(Animation animation) {
			}
		});
		img.startAnimation(fadeOut);
	}

	/**
	 * Animation fade in for View
	 */
	public static void fadeInView(final View view, int duration) {
		Animation fadeIn = new AlphaAnimation(0, 1);
		fadeIn.setInterpolator(new AccelerateInterpolator());
		fadeIn.setDuration(duration);
		fadeIn.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				view.setVisibility(View.VISIBLE);
			}
		});
		view.startAnimation(fadeIn);
	}

	public static void simpleAnimationIn(final View img, Context context, int animation) {
		Animation anim = AnimationUtils.loadAnimation(context, animation);
		anim.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
				img.setVisibility(View.VISIBLE);
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
			}
		});
		img.startAnimation(anim);
	}

	/**
	 * fadeIn a view while another view fadeOut </br> See : {@link Animation}
	 * 
	 * @param viewIn
	 *        must not be <code>null</code>
	 * @param viewOut
	 *        same than <code>viewIn</code>
	 * @param duration
	 *        in millisecond
	 */
	public static void crossfade(final View viewIn, final View viewOut, int duration) {
		Animation fadeIn = new AlphaAnimation(0, 1);
		fadeIn.setDuration(duration);
		Animation fadeOut = new AlphaAnimation(1, 0);
		fadeOut.setDuration(duration);
		fadeOut.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				viewOut.setVisibility(View.GONE);
			}
		});
		fadeIn.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				viewIn.setVisibility(View.VISIBLE);
			}
		});
		viewOut.startAnimation(fadeOut);
		viewIn.startAnimation(fadeIn);
	}

	/**
	 * Create a blur effect on a bitmap<br>
	 * Heavy on cpu use :/
	 */
	public static Bitmap applyGaussianBlur(Bitmap src) {
		double[][] GaussianBlurConfig = new double[][] { { 1, 2, 1 }, { 2, 4, 2 }, { 1, 2, 1 } };
		ConvolutionMatrix convMatrix = new ConvolutionMatrix(3);
		convMatrix.applyConfig(GaussianBlurConfig);
		convMatrix.Factor = 3;
		convMatrix.Offset = 0;
		return ConvolutionMatrix.computeConvolution3x3(src, convMatrix);
	}

	public static boolean isEllipsize(TextView tv) {
		Layout l = tv.getLayout();
		if (l != null) {
			int lines = l.getLineCount();
			if (lines > 0) {
				int ellipsisCount = l.getEllipsisCount(lines - 1);
				if (ellipsisCount > 0) {
					return true;
				}
			}
		}
		return false;
	}
}
